
#include <scene/sector.h>
#include <scene/entitynode.h>
#include <scene/light.h>
#include <scene/portal.h>
#include <assert.h>

ceSector::ceSector()
  : iObject ()
  , _lastScannedFrame (0)
{
	CE_OBJECT_CONSTR;
}

void ceSector::AddNode(ceNode *node)
{
  if(!node)
    {
      return;
    }

  node->AddRef();

  _nodes.push_back (node);
	node->SetSector (this);

	AddLightNode (node);
}

void ceSector::RemoveNode(ceNode *node)
{
  std::list<ceNode*>::iterator it;
  for (it = _nodes.begin (); it != _nodes.end (); ++it)
    {
      ceNode* n = *it;
      if (n == node)
        {
					n->SetSector (0);
          _nodes.erase (it);
          node->Release();
          return;
        }
    }
}

void ceSector::AddLightNode (ceNode* node)
{
  if (node->GetNodeType () != NT_EntityNode)
		{
			return;
		}

	ceEntityNode* eNode = static_cast<ceEntityNode*>(node);
	ceLightObject* lo = eNode->GetLight ();
	if (!lo)
		{
			return;
		}

	AddLight (lo->GetLight ());
	_lights.insert (lo->GetLight ());
}

void ceSector::AddLight (ceLight* light)
{
	_lights.insert (light);
}


NodeList& ceSector::GetNodes()
{
  return _nodes;
}

void ceSector::FindSectorLights (bool clearLights)
{
	if (clearLights)
		{
			_lights.clear ();
		}

	std::list<ceNode*>::iterator it;
  for (it = _nodes.begin (); it != _nodes.end (); ++it)
    {
      ceNode* n = *it;
			n->FindLights (this);
		}
}

void ceSector::ApplyLights ()
{
  std::list<ceNode*>::iterator it;
  for (it = _nodes.begin (); it != _nodes.end (); ++it)
    {
      ceNode* n = *it;
			n->ClearLights ();
			std::set<ceLight*>::iterator lit;
			for (lit = _lights.begin (); lit != _lights.end (); lit++)
				{
					n->TestAndAddLight (*lit);
				}
		}
}


cePortal* ceSector::Connect(ceSector* sector)
{
	cePortal* portal = GetPortal (sector);
	if (!portal)
		{
			// create a new portal between the two sectors
			portal = new cePortal (this, sector);

			// both sectors must have the same portal between it in sync
			sector->_portals.push_back(portal);
			_portals.push_back (portal);
		}
	return portal;
}

cePortal* ceSector::GetPortal (ceSector* sector)
{
	for (unsigned i=0, j=_portals.size (); i<j; i++)
		{
			cePortal* portal = _portals[i];
			const ceSector* s0 = portal->GetSector ((unsigned int)0);
			const ceSector* s1 = portal->GetSector ((unsigned int)1);
			if (s0 == this && s1 == sector ||
				  s1 == this && s0 == sector)
				{
					return portal;
				}
		}

	return 0;
}

const cePortal* ceSector::GetPortal (const ceSector* sector) const
{
	for (unsigned i=0, j=_portals.size (); i<j; i++)
		{
			cePortal* portal = _portals[i];
			const ceSector* s0 = portal->GetSector ((unsigned int)0);
			const ceSector* s1 = portal->GetSector ((unsigned int)1);
			if (s0 == this && s1 == sector ||
				  s1 == this && s0 == sector)
				{
					return portal;
				}
		}

	return 0;
}

unsigned ceSector::GetNumberOfPortals () const
{
	return _portals.size ();
}

cePortal* ceSector::GetPortal (unsigned idx)
{
	assert (idx < _portals.size ());
	return _portals[idx];
}

const cePortal* ceSector::GetPortal (unsigned idx) const
{
	assert (idx < _portals.size ());
	return _portals[idx];
}


void ceSector::SetLastScannedFrame (unsigned frame)
{
	_lastScannedFrame = frame;
}

unsigned ceSector::GetLastScannedFrame () const
{
	return _lastScannedFrame;
}
